package com.xuzimian.globaldemo.jmx.standard;

import com.sun.jdmk.comm.HtmlAdaptorServer;
import org.junit.Test;

import javax.management.*;
import javax.management.remote.*;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;


/**
 * @program: global-demo
 * @description:
 * @author: xzm
 * @create: 2019-01-24 15:26
 **/
public class StandardMBeanAgentDemo {


    /**
     * 可以用使用jdk中的Jconsole.exe工具，找到对应的进程进行连接，在MBean中进行操作。
     * 注意：由于本方法是使用Junit，所以进程名是Juint起始的。
     *
     * @throws JMException
     * @throws Exception
     */
    @Test
    public void testJMXByJconsole() throws JMException, Exception {
        // 下面这种方式不能再JConsole中使用
        // MBeanServer server = MBeanServerFactory.createMBeanServer();
        // 首先建立一个MBeanServer,MBeanServer用来管理我们的MBean,通常是通过MBeanServer来获取我们MBean的信息，间接
        // 调用MBean的方法，然后生产我们的资源的一个对象。
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();

        String domainName = "HLMBean";

        ObjectName helloName = new ObjectName(domainName + ":name=HelloWorld");
        // 将new Hello()这个对象注册到MBeanServer上去
        Hello hello = new Hello();
        hello.setName("hl");

        mBeanServer.registerMBean(hello, helloName);
        System.in.read();
    }


    /**
     * 启动后访问http://localhost:8082/
     *
     * @throws JMException
     * @throws Exception
     */
    @Test
    public void testJMXByHtml() throws JMException, Exception {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        String domainName = "HLMBean";
        ObjectName helloName = new ObjectName(domainName + ":name=HelloWorld");
        // 将new Hello()这个对象注册到MBeanServer上去
        Hello hello = new Hello();
        hello.setName("hl");
        mBeanServer.registerMBean(hello, helloName);

        //HtmlAdaptor 方式
        // Distributed Layer, 提供了一个HtmlAdaptor。支持Http访问协议，并且有一个不错的HTML界面，这里的Hello就是用这个作为远端管理的界面
        // 事实上HtmlAdaptor是一个简单的HttpServer，它将Http请求转换为JMX Agent的请求
        ObjectName adapterName = new ObjectName(domainName + ":name=htmladapter,port=8082");

        HtmlAdaptorServer adapter = new HtmlAdaptorServer();
        adapter.start();
        mBeanServer.registerMBean(adapter, adapterName);
        System.in.read();
    }

    /**
     * 启动后可以编写rmi远程调用来连接，或者可以使用Jconsole进行远程访问：
     * 在Jconsole的远程访问中输入 localhost:1099
     * @throws JMException
     * @throws Exception
     */
    @Test
    public void testJMXByRMI() throws JMException, Exception {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();

        ObjectName helloName = new ObjectName("jmxBean:name=hello");
        // 将new Hello()这个对象注册到MBeanServer上去
        Hello hello = new Hello();
        hello.setName("hl");
        mBeanServer.registerMBean(hello, helloName);

        int rmiPort = 1099;
        Registry registry = LocateRegistry.createRegistry(rmiPort);
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxBean");
        JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer);
        jmxConnector.start();
        System.in.read();
    }


    /**
     * 对jmx暴露的rmi进行连接调用
     * @param args
     * @throws IOException
     * @throws Exception
     * @throws NullPointerException
     */
    public static void main(String[] args) throws IOException, Exception, NullPointerException
    {
        JMXServiceURL url = new JMXServiceURL
                ("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxBean");
        JMXConnector jmxc = JMXConnectorFactory.connect(url,null);

        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
        //ObjectName的名称与前面注册时候的保持一致
        ObjectName mbeanName = new ObjectName("jmxBean:name=hello");

        System.out.println("Domains ......");
        String[] domains = mbsc.getDomains();

        for(int i=0;i<domains.length;i++)
        {
            System.out.println("doumain[" + i + "]=" + domains[i] );
        }

        System.out.println("MBean count = " + mbsc.getMBeanCount());
        //设置指定Mbean的特定属性值
        //这里的setAttribute、getAttribute操作只能针对bean的属性
        //例如对getName或者setName进行操作，只能使用Name，需要去除方法的前缀
        mbsc.setAttribute(mbeanName, new Attribute("Name","杭州"));
        mbsc.setAttribute(mbeanName, new Attribute("Age","1990"));
        String age = (String)mbsc.getAttribute(mbeanName, "Age");
        String name = (String)mbsc.getAttribute(mbeanName, "Name");
        System.out.println("age=" + age + ";name=" + name);

        HelloMBean proxy = MBeanServerInvocationHandler.
                newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);
        proxy.helloWorld();
        proxy.helloWorld("migu");
        proxy.getTelephone();
        //invoke调用bean的方法，只针对非设置属性的方法
        //例如invoke不能对getName方法进行调用
        mbsc.invoke(mbeanName, "getTelephone", null, null);
        mbsc.invoke(mbeanName, "helloWorld",
                new String[]{"I'll connect to JMX SocketServerAndClientDemo via client2"}, new String[]{"java.lang.String"});
        mbsc.invoke(mbeanName, "helloWorld", null, null);
    }

}
